        TITL DAI FIRMWARE D23D-D3F3  V1.0  Rev.1
        ORG   :D23D
*
*
*
*  =============
*** I/O HANDLER ***
*  =============
*
*
*********************
* RUN basiccmd SAVE *
*********************
*
* Valid as direct command and in program.
* Clears the Heap, zeroes all variables, evaluate
* an evt. program name and writes a file of type
* 0 (BASIC) on tape.
*
* Exit: HL: Points to end symboltable.
*       DE: Length symboltable.
*       BC: Updated.
*
RSAVE   CALL  :CB23     Empty HEAP + symtab
        LHLD  :02A1     Get start symtab
        XCHG            in DE
        LHLD  :02A3     End symtab in HL
        CALL  :DE1A     Calculate length symtab
        PUSH  H         Preserve length symtab
        LHLD  :029F     Get start textbuf
        XCHG            in DE
        CALL  :DE1A     Calculate length textbuf
        PUSH  H         Preserve length textbuf
        PUSH  D         Preserve start textbuf
        CALL  :E791     (0) Evaluate program name
        NOP
        NOP
        NOP
        MVI   A,:30     File type byte 0
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        NOP
        CALL  :02C5     Write fileleader, flagbyte,
 REM file type byte, name length
 REM and name.
        POP   H         Start textbuf in HL
        POP   D         Length textbuf in DE
        CALL  :02C8     Write length and contents
 REM textbuf
        POP   D         Length symtab in DE
        JMP   :D7D8     Write length and contents
 REM symtab + file trailer
*
        DATA  :FF
*
*********************
* RUN basiccmd LOAD *
*********************
*
* Valid as direct command and in program.
* Clears Heap and all variables. Evaluates name
* of program, updates BC. Required file type: 0.
* C is set to print type/name or not.
* A file (type 0: Basic) is read from tape. When
* a file has been found, the textbuffer and the
* symboltable are loaded and the pointers updated.
* When loading during program run: the program
* continues with the program just loaded.
*
* Exit: No error: BC: Updated.
*                 DE: Begin screen RAM.
*                 HL: End symbol table.
*
RLOAD   CALL  :CB23     Empty HEAP + symtab
        CALL  :E791     (0) Evaluate programname
        PUSH  B
        NOP
        NOP
        NOP
        NOP
        MVI   B,:30     File type byte 0
        PUSH  H         Preserve length name reqd
        LHLD  :0100     Get CURRNT
        MOV   A,H
        ORA   L         Load during run program?
        MVI   C,:00
        JNZ   :D289     If during run; C=00
        DCR   C         Else C=FF
RLD10   POP   H
        CALL  :02CE     Switch on cassette motors;
 REM read header + name
        LHLD  :02A5     Get end free RAM
        XCHG            Max. RAM in DE
        LHLD  :029F     Start textbuf in HL
        CALL  :02D1     Load textbuffer
        SHLD  :02A1     Store end textbuffer
        CC    :02D1     Load symboltable
        CALL  :D71A     Store end symtab; stop
 REM cassette motors.
        POP   B
        EI              Enable interrupts
        JNC   :D2A8     If loading error
        MVI   A,:00     No loading error
        RET
*
*********************
* RUN LOADING ERROR *
*********************
*
* The programbuffers are restored. A error message
* is printed.
*
RLERR   PUSH  PSW
        CALL  :DEB5     Run 'NEW'
        POP   PSW
        LXI   H,:0000
        SHLD  :0100     Set CURRNT=0
RLEAR   ADI   :0B
        JMP   :D9F5     Run 'LOADING ERROR ..'
*
*
******************
* OPEN TAPE FILE *
******************
*
* Entry: A:  File type.
*        HL: Points to file name.
* Exit:  HL: Points beyond file name.
*        DE: Length of name.
*        BC: Preserved.
*        A:  Checksum on name.
*
CWOPEN  PUSH  PSW
        CALL  :D720     Init. write file leader
        POP   PSW
        CALL  :D509     Write file type byte
        JMP   :D7F8     Get name length, write it
 REM on tape, incl. its c.s.
*
**********************
* RUN basiccmd CHECK *
**********************
*
* Valid as direct command only.
* Checks on file type and name. For all files
* with type <3, a checksum on all data is done.
* This routine remains in a endless loop and
* can be aborted with BREAK only.
*
*RCHECK
CHK10   LXI   H,:0000   No program name given
        LXI   B,:00FF   Any file type
        NOP
        NOP
        CALL  :02CE     Read file header, file
 REM type and name; print
 REM type and name
        NOP
        CPI   :33
        JNC   :D2EB     If file type >=3: no check
 REM on checksum
 REM
* Test checksum:
 REM
        INR   C         BC=0
        CALL  :D7E6     Set A=0, read + check
 REM a data block
        CZ    :02D7     Read + check next block
        JNZ   :D2E6     If reading error
        CALL  :DAFF     Print 'OK', car.ret
        DBL   :DBC0
        JMP   :D2C3     Wait for next file
 REM
* If checksum error:
 REM
CHK20   CALL  :DAFF     Print 'BAD'
        DBL   :DBDB
CHK30   CALL  :DD5E     Print car.ret
        JMP   :D2C3     Wait for next file
*
***********************
* WRITE BLOCK ON TAPE *
***********************
*
* Entry: HL: Startaddres block.
*        DE: Length block.
* Exit:  HL: 1st byte after block.
*        A: Checksum on block contents.
*        BCDE preserved.
*
CWBLK   PUSH  B
        PUSH  D
        NOP
        CALL  :D316     Write block length +
 REM c.s. on length
        MVI   B,:56     Initial checksum value
LD34    MOV   A,D
        ORA   E
        JZ    :D307     If all bytes written
        DCX   D
        MOV   A,M       Get byte of block
        INX   H         Point to next byte
        CALL  :D30F     Write byte, update checksum
        JMP   :D2F9     Next byte
 REM
* If all data written: write c.s. on block:
 REM
LD35    MOV   A,B       Get calculated checksum
        CALL  :D509     Write checksum
        NOP
        POP   D
        POP   B
        RET
*
*******************************
* WRITE BYTE, UPDATE CHECKSUM *
*******************************
*
* Entry: Byte to be written in A.
*        Checksum in B.
* Exit:  New checksum in B; A corrupted.
*        CDEHL preserved.
*
LD36    CALL  :D509     Write byte
        XRA   B
        RLC
        MOV   B,A       Update checksum
        RET
*
***************************************
* WRITE BLOCK LENGTH, UPDATE CHECKSUM *
***************************************
*
* Entry: DE: length block.
* Exit:  DEHL preserved.
*
LD37    MVI   B,:56     Init checksum
        MOV   A,D       Get highest length byte,
        CALL  :D30F     write it, update c.s.
        MOV   A,E       Get lowest length byte,
        CALL  :D30F     write it, update c.s
        MOV   A,B       Get checksum
        CALL  :D509     Write checksum on length
        RET
 REM
**********************
* START FILE READING *
**********************
*
* Entry: HL: Address length byte of name requested.
*        B:  File type byte requested.
*        C:  00 when reading during run program,
*            else FF.
* Exit:  A:  File type byte.
*        HL: Points to 1st byte of name requested.
*        DE: Length name requested.
*        BC: preserved.
*
CROPEN  PUSH  PSW
        CALL  :D7FF     Switch cassette motors on,
 REM init. registers
RPN10   NOP
        NOP
        NOP
        NOP
        NOP
        POP   PSW
        CALL  :D3F4     Read file header
        PUSH  PSW
        CALL  :D78A     Display file type byte
        SUB   B
        CALL  :D3A2     Read and check header,
 REM program name, file type byte
        ORA   A         0 if everything OK.
        JNZ   :D783     If failure
        POP   PSW
        RET
*
**************
* READ BLOCK *
**************
*
* Read length, contents and checksum of a block
*
* Entry: HL: Addr. where to dump data read.
*        DE: End free space.
* Exit:  CY=1: No error:
*           HL: Next free address.
*           BCDE preserved; AF corrupted.
*        CY=0: Loading error:
*           BCDEHL preserved.
*           A: Type of loading error.
*
CRBLK   PUSH  B
        PUSH  D
        PUSH  H
        CALL  :D790     Calculate free RAM space
        XCHG            Free RAM in DE
        CALL  :D38D     Read block length + c.s.
 REM length in HL
        JC    :D37E     If loading error 3
        ORA   A
        MVI   A,:00     Loading error 0
        JNZ   :D380     If checksum error 0
        PUSH  H         Save length block
        DAD   D         Calculate free RAM
        POP   D         Get length block
        INR   A         Loading error 1
        POP   H
        PUSH  H         Restore begin addr.
        JC    :D380     If loading error 1
        MVI   B,:56     Init checksum
LBK10   MOV   A,D
        ORA   E
        JZ    :D36F     If whole block read
        DCX   D
        CALL  :D384     Read next byte, update c.s
        JC    :D37E     If loading error 3
        MOV   M,A       Store byte in buffer
        INX   H
        JMP   :D35E     Next byte
 REM
* If whole block read:
 REM
LBK20   CALL  :D4D4     Read checksum block contents
        JC    :D37E     If loading error 3
        CMP   B         Check checksum
        MVI   A,:02     Loading error 2
        JNZ   :D380     If loading error 2
        JMP   :C6B4     CY=1, return: no error
 REM
* If loading error:
 REM
LBK40   MVI   A,:03     Loading error 3
LOERR   ORA   A
        JMP   :C6B6     Return with CY=0: error
*
*********************************
* READ BYTE, CALCULATE CHECKSUM *
*********************************
*
* Entry: B: Checksum.
* Exit:  A: Byte read.
*        B: Updated checksum.
*        CDEHL preserved.
*
INSC    CALL  :D4D4     Read byte
RBUEX   PUSH  PSW
        XRA   B         Calculate checksum
        RLC
        MOV   B,A       Store new value
        POP   PSW
        RET
*
********************
* READ NAME LENGTH *
********************
*
* Entry: No conditions.
* Exit:  HL: Length name read.
*        A:  Result checksum check (0 if OK).
*        BCDE: preserved.
*        CY=0: O.K.; CY=1: Out of data.
*
INLNG   PUSH  B
        MVI   B,:56     Init. checksum
        CALL  :D384     Read highest length byte
 REM and update checksum
        MOV   H,A
        CNC   :D384     Read lowest length byte
 REM and update checksum
        MOV   L,A
        CNC   :D4D4     Read checksum on length
RHLEX   PUSH  PSW
        SUB   B         Check checksum
        MOV   B,A
        POP   PSW
        MOV   A,B
        POP   B
        RET
*
*******************************************
* READ + CHECK PROGRAM NAME AND FILE TYPE *
*******************************************
*
* Routine searches for proper file name by
* reading file name and compare it with name
* requested.
*
* Entry: A:  Evt. difference in file type byte
*            read and requested.
*        B:  Requested file type.
*        C:  00 during run program, else FF.
*        DE: Length requested.
*        HL: Address 1st byte name requested.
* Exit:  BCDEHL preserved.
*        A=0: All OK.
*        A=1: Loading error 1.
*
CMBLK   PUSH  B         Save file type + RUN flag
        PUSH  H         Save addr reqd name
        MOV   B,A       Store deviation file type
MBK10   PUSH  D         Save req. name length
        PUSH  H
        CALL  :D38D     Read + check program name
 REM evt. c.s.failure in A
        JC    :D3ED     If reading error
        ORA   A
        JNZ   :D3ED     If checksum error
        PUSH  H         Save length name on tape
        CALL  :DE1A     Calculate difference name
 REM lengths reqd and on tape
        MOV   A,H
        ORA   L
        MOV   H,A       Difference in H
        MOV   L,B       Difference file type in L
        POP   D         Get length name on tape
        MVI   B,:56     Initiate checksum
MBK20   XTHL            Get byte reqd name
        MOV   A,D
        ORA   E         Length name on tape = 0 ?
        JZ    :D3D8     If length = 0, or whole
 REM name read.
        DCX   D
        CALL  :D384     Read bytes of name, update
 REM checksum
        JC    :D3ED     If reading error
        DCR   C
        INR   C         Load during run?
        PUSH  PSW       Save length name on tape
        CNZ   :D7EB     Display program name
        POP   PSW       Get byte of name on tape
        XRA   M         Compare with name reqd
        INX   H
        XTHL            Get 'difference flag'
        ORA   H         Update it
        MOV   H,A       and store it in H
        JMP   :D3BC     Next byte
 REM
* If whole name read:
 REM
MBK30   CALL  :D4D4     Read c.s on name contents
        JC    :D3ED     If reading error
MBEX    XRA   B         Check checksum
        POP   H
        ORA   L         Check file type
        MOV   L,A
        POP   D         Get length req. name
        MOV   A,D
        ORA   E         No name requested ?
        JZ    :D3E9     If load without name
        MOV   A,H       Difference in names?
MBK40   ORA   L         Take also other checks in
 REM account
MBK45   POP   H
        POP   B
        RET
 REM
* If error:
 REM
MBK50   POP   H
        POP   D
        MVI   A,:01     Loading error 1
        JMP   :D3E9
*
*
*
        UNL
RCHECK  EQU CHK10
        LST
        END
